<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>图片旋转验证</title>
    <style>
      /* css样式 */
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }

      body {
        display: flex;
        justify-content: center;
        align-items: center;
        min-height: 100vh;
        background-color: #f5f5f5;
        font-family: Arial, sans-serif;
      }

      .captcha-container {
        width: 400px;
        padding: 30px;
        background-color: white;
        border-radius: 12px;
        box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
      }

      h2 {
        text-align: center;
        margin-bottom: 25px;
        color: #333;
      }

      .image-container {
        text-align: center;
        margin-bottom: 30px;
      }

      img {
        width: 200px;
        height: 200px;
        object-fit: cover;
        border-radius: 50%;
        transition: transform 0.05s ease-out;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
      }

      .slider-container {
        position: relative;
        height: 30px;
        margin-bottom: 20px;
      }

      .slider-track {
        position: absolute;
        top: 50%;
        left: 0;
        width: 100%;
        height: 6px;
        background-color: #e0e0e0;
        border-radius: 3px;
        transform: translateY(-50%);
      }

      .slider-progress {
        position: absolute;
        top: 0;
        left: 0;
        height: 100%;
        width: 0;
        background-color: #4285f4;
        border-radius: 3px;
        transition: width 0.05s ease-out;
      }

      .slider-thumb {
        position: absolute;
        top: 50%;
        left: 0;
        width: 24px;
        height: 24px;
        background-color: #4285f4;
        border-radius: 50%;
        box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
        transform: translate(-50%, -50%);
        cursor: pointer;
        transition: background-color 0.2s, transform 0.2s;
        touch-action: none;
      }

      .slider-thumb:hover {
        background-color: #3367d6;
      }

      .slider-thumb:active {
        transform: translate(-50%, -50%) scale(0.95);
      }

      .status {
        text-align: center;
        margin-bottom: 15px;
        min-height: 24px;
        font-size: 16px;
        font-weight: 500;
      }

      .timer {
        text-align: center;
        margin-bottom: 20px;
        color: #666;
        font-size: 14px;
      }

      .success {
        color: #0f9d58;
      }

      .error {
        color: #db4437;
      }

      .pending {
        color: #4285f4;
      }
    </style>
  </head>
  <body>
    <div class="captcha-container">
      <h2>请旋转图片至正确方向</h2>
      <div class="image-container">
        <img id="verifyImage" src="../images/龙猫.jpg" alt="验证图片" />
      </div>
      <div class="slider-container">
        <div class="slider-track">
          <div class="slider-progress" id="sliderProgress"></div>
        </div>
        <div class="slider-thumb" id="sliderThumb"></div>
      </div>
      <div class="timer"><span id="timer">0.00</span> 秒</div>
      <div class="status" id="status">请拖动滑块旋转图片</div>
    </div>

    <script>
      //js逻辑
      // 获取DOM元素
      const verifyImage = document.getElementById("verifyImage");
      const sliderThumb = document.getElementById("sliderThumb");
      const sliderProgress = document.getElementById("sliderProgress");
      const status = document.getElementById("status");
      const timer = document.getElementById("timer");

      // 初始变量
      let startAngle = Math.floor(Math.random() * 280) + 40; // 40-319度之间
      let currentRotation = startAngle; // 不使用取余，记录实际旋转角度
      let isDragging = false;
      let startTime = 0;
      let timerInterval = null;
      const SUCCESS_THRESHOLD = 10; // 允许的误差范围(度)
      let lastClientX = 0;
      let animationFrameId = null;

      // 初始化图片旋转角度
      verifyImage.style.transform = `rotate(${startAngle}deg)`;

      // 滑块拖动逻辑
      sliderThumb.addEventListener("mousedown", startDrag);
      sliderThumb.addEventListener("touchstart", startDrag, { passive: false });

      document.addEventListener("mouseup", endDrag);
      document.addEventListener("touchend", endDrag);

      // 开始拖动
      function startDrag(e) {
        e.preventDefault();
        isDragging = true;
        sliderThumb.classList.add("active");
        lastClientX = e.clientX || e.touches[0].clientX;

        // 开始计时
        startTime = Date.now();
        if (timerInterval) clearInterval(timerInterval);
        timerInterval = setInterval(updateTimer, 10);

        // 更新状态
        status.textContent = "正在旋转...";
        status.className = "status pending";

        // 添加移动事件监听
        document.addEventListener("mousemove", handleDrag);
        document.addEventListener("touchmove", handleDrag, { passive: false });
      }

      // 处理拖动
      function handleDrag(e) {
        if (!isDragging) return;
        e.preventDefault();

        // 取消上一帧动画
        if (animationFrameId) {
          cancelAnimationFrame(animationFrameId);
        }

        // 使用requestAnimationFrame优化性能
        animationFrameId = requestAnimationFrame(() => {
          const clientX = e.clientX || e.touches[0].clientX;

          // 避免处理重复位置
          if (clientX === lastClientX) return;
          lastClientX = clientX;

          const sliderRect =
            sliderProgress.parentElement.getBoundingClientRect();
          let newPosition = clientX - sliderRect.left;

          // 限制在轨道范围内
          newPosition = Math.max(0, Math.min(newPosition, sliderRect.width));

          // 计算百分比和对应的角度
          const percentage = newPosition / sliderRect.width;
          const rotationAngle = percentage * 360;

          // 更新UI（不使用取余）
          sliderProgress.style.width = `${percentage * 100}%`;
          sliderThumb.style.left = `${percentage * 100}%`;
          currentRotation = startAngle + rotationAngle;
          verifyImage.style.transform = `rotate(${currentRotation}deg)`;
        });
      }

      // 结束拖动（验证逻辑）
      function endDrag() {
        if (!isDragging) return;
        isDragging = false;
        sliderThumb.classList.remove("active");

        // 停止计时
        if (timerInterval) clearInterval(timerInterval);
        const elapsedTime = (Date.now() - startTime) / 1000;

        // 移除移动事件监听
        document.removeEventListener("mousemove", handleDrag);
        document.removeEventListener("touchmove", handleDrag);

        // 取消动画帧
        if (animationFrameId) {
          cancelAnimationFrame(animationFrameId);
          animationFrameId = null;
        }

        // 计算与目标角度(0度)的差值（考虑实际旋转圈数）
        const normalizedAngle = currentRotation % 360;
        const angleDiff = Math.min(
          Math.abs(normalizedAngle),
          360 - Math.abs(normalizedAngle)
        );

        if (angleDiff <= SUCCESS_THRESHOLD) {
          // 验证成功
          status.textContent = "验证通过!";
          status.className = "status success";

          // 禁用滑块
          sliderThumb.style.pointerEvents = "none";
          sliderThumb.style.opacity = "0.6";

          // 显示成功弹窗
          setTimeout(() => {
            alert(`验证成功！用时 ${elapsedTime.toFixed(2)} 秒`);
            resetCaptcha();
          }, 500);
        } else {
          // 验证失败，重置进度和计时器
          status.textContent = "验证失败，请重试";
          status.className = "status error";

          // 轻微震动效果
          verifyImage.classList.add("shake");
          setTimeout(() => {
            verifyImage.classList.remove("shake");
            resetProgress();
          }, 500);
        }
      }

      // 更新计时器
      function updateTimer() {
        const elapsedTime = (Date.now() - startTime) / 1000;
        timer.textContent = elapsedTime.toFixed(2);
      }

      // 重置进度（保留当前图片角度）
      function resetProgress() {
        sliderProgress.style.width = "0%";
        sliderThumb.style.left = "0%";
        timer.textContent = "0.00";
        status.textContent = "请拖动滑块旋转图片";
        status.className = "status";

        // 重置起始角度，但保留当前旋转状态
        startAngle = currentRotation;
      }

      // 重置验证码（全新开始）
      function resetCaptcha() {
        // 重置变量
        startAngle = Math.floor(Math.random() * 280) + 40;
        currentRotation = startAngle;
        isDragging = false;
        if (timerInterval) clearInterval(timerInterval);

        // 重置UI
        verifyImage.style.transform = `rotate(${startAngle}deg)`;
        sliderProgress.style.width = "0%";
        sliderThumb.style.left = "0%";
        sliderThumb.style.pointerEvents = "auto";
        sliderThumb.style.opacity = "1";
        timer.textContent = "0.00";

        status.textContent = "请拖动滑块旋转图片";
        status.className = "status";
      }

      // 添加CSS动画
      const style = document.createElement("style");
      style.textContent = `
            .shake {
                animation: shake 0.5s ease-in-out;
            }
            @keyframes shake {
                0%, 100% { transform: rotate(${currentRotation}deg); }
                25% { transform: rotate(${currentRotation - 5}deg); }
                75% { transform: rotate(${currentRotation + 5}deg); }
            }
            .slider-thumb.active {
                background-color: #3367d6;
                transform: translate(-50%, -50%) scale(1.05);
            }
        `;
      document.head.appendChild(style);
    </script>
  </body>
</html>
